
#ifndef _ANDROID
#include <iostream>
#endif
#include "fmbLog.h"

#ifndef _ANDROID
using namespace std;
#endif
using namespace fm::base;

Log *Log::m_instance = NULL;
Mutex Log::m_mutex;

Log::Log() {}

Log::~Log() {
  Log::m_instance = NULL;
  Lock lock(m_lockingPolicy);
  for (int i = m_sinkList.num() - 1; i >= 0; --i) {
    delete m_sinkList[i];
    m_sinkList.remove(i);
  }
}

void Log::addSink(LogSink *sink) {
  Log &log = Singleton<Log>::instance();
  Log::Lock lock(log.m_lockingPolicy);
  log.m_sinkList.add(sink);
}

void Log::msg(Level level, const char *pattern, va_list args) {
  Lock lock(m_lockingPolicy);

#ifdef _WIN32
  if (vsnprintf_s(m_msgBuf, MESSAGE_BUFFER_SIZE, pattern, args) < 0)
#else
  if (vsnprintf(m_msgBuf, MESSAGE_BUFFER_SIZE, pattern, args) < 0)
#endif
    throw Err("Log: error during printing log message");

  for (int i = 0; i < m_sinkList.num(); ++i)
    m_sinkList[i]->msg(level, m_msgBuf);
}

void Log::info(const char *pattern, ...) {
  va_list args;
  va_start (args, pattern);
  Singleton<Log>::instance().msg(INFO, pattern, args);
  va_end (args);

}
void Log::warn(const char *pattern, ...) {
}
void Log::err(const char *pattern, ...) {
}
void Log::debug(const char *pattern, ...) {
}
void Log::trace(const char *pattern, ...) {
}

LogSink::~LogSink() {}

void LogConsoleSink::msg(Log::Level level, const char *msg) {
#ifndef _ANDROID
  switch (level) {
  case Log::INFO: cout << "INFO: " << msg << endl; break;
  case Log::WARN: cout << "WARN: " << msg << endl; break;
  case Log::ERR: cout   << "ERR: " << msg << endl; break;
  case Log::DEBUG: cout << "DEBUG: " << msg << endl; break;  
  case Log::TRACE: cout << "TRACE: " << msg << endl; break;
  }
#else
  switch (level) {
  case Log::INFO: printf("INFO: %s\n", msg); break;
  case Log::WARN: printf("WARN: %s\n", msg); break;
  case Log::ERR: printf("ERR: %s\n", msg); break;
  case Log::DEBUG: printf("DEBUG: %s\n", msg); break;  
  case Log::TRACE: printf("TRACE: %s\n", msg); break;
  }
#endif
}

LogConsoleSink::~LogConsoleSink() {}

void LogJNISink::msg(Log::Level level, const char *msg) {}

LogJNISink::~LogJNISink() {}
